home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 2 / LSD and 17bit Compendium Deluxe - Volume II.iso / a / prog / cprog / dmssplit.lha / dmssplit.c next >
Encoding:
C/C++ Source or Header  |  1992-06-17  |  17.7 KB  |  847 lines

  1. /*
  2.  * This is a program for splitting "dms" files on unix systems.
  3.  * Its usage is:
  4.     dmssplit <option> file
  5.  
  6.  * With no option, dmssplit will create two files named "1_file" and "2_file"
  7.  * (I was lazy about that), with the first being approximately 70% in size
  8.  * of the original, and the second 30% (how did you guess?).
  9.  
  10.  * Options are:
  11.     -h or -? : little help
  12.     -t <n> : chose n to be the track number where the file is splitted
  13.     -p <n> : chose n to be the size percentage of the first file
  14.     -d : debug mode. Very verbose.
  15.  
  16.  * Option -p will eventually supersede option -t.
  17.  
  18.  * The code is pretty basic Unix, there should be no compiling problem,
  19.  * just do "cc dmssplit.c -o dmssplit" to get the executable.
  20.  * Care was taken to read and use the data as char arrays to avoid
  21.  * alignement problems inside structures (a main portability nuisance).
  22.  * But lint does not like that!
  23.  
  24.  * WARNING: I had no time to fully test this one. "dmscheck" tells the 
  25.  *          resulting files are good, but I didn't actually try them.
  26.  *          KEEP THE ORIGINAL FILE !!!!
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <sys/types.h>
  31. #include <sys/file.h>
  32.  
  33. #define RATIO 70
  34.  
  35. typedef char BYTE;
  36. typedef unsigned char UBYTE;
  37. typedef short SHORT;
  38. typedef unsigned short USHORT;
  39. typedef long LONG;
  40. typedef unsigned long ULONG;
  41.  
  42. #define SILENT 0
  43. #define NORMAL 1
  44. #define VERBOSE 2
  45. #define DEBUG  3
  46.  
  47. int MessageLevel = NORMAL ;
  48. int TrackNumber = 0 ;
  49. int Percentage = 0 ;
  50.  
  51. #define NOERROR 0
  52. #define NONFATAL 1
  53. #define FATAL 2
  54.  
  55. int ErrorFlag = NOERROR ;
  56.  
  57. char * FileName ;
  58.  
  59. int FirstTrack = 0 ;
  60. int MediumTrack = 0 ;
  61. int LastTrack = 0 ;
  62. int LastTrackRead = 0 ;
  63.  
  64. int FdIn ;
  65. int FdOut ;
  66.  
  67. char IoBuf[12000] ;
  68. USHORT Crc ;
  69.  
  70. #define MAXTRACKS 85
  71. int CompSizes[MAXTRACKS] ;
  72. int RawSizes[MAXTRACKS] ;
  73. int CompText ;
  74. int RawText ;
  75.  
  76. /* Format of a simple DMS file:
  77.  
  78.     Ident File_Head CRC Track_Head CRC Data Track_Head CRC Data  ....
  79.  
  80. */
  81.  
  82. char Ident[6] ;            /* "DMS!" */
  83.  
  84. /* 
  85.    These macros are used to access the file header components
  86.    with no concern about the alignement requirements of each machine.
  87. */
  88.  
  89. #define DHEAD_FROM(tab)  (*((SHORT *) (tab+12)))
  90. #define DHEAD_TO(tab)    (*((SHORT *) (tab+14)))
  91. #define DHEAD_CSIZE(tab) (*((ULONG *) (tab+16)))
  92. #define DHEAD_SIZE(tab)  (*((ULONG *) (tab+20)))
  93. #define DHEAD_MODE(tab)  (*((SHORT *) (tab+48)))
  94.  
  95. char DHeaderIn[50] ;
  96. char DHeaderOut[50] ;
  97.  
  98. struct File_Head        /*offset - sizeof(File_Head) = 50 */
  99. {
  100.     long u1  ;        /* 0 -  ???? */
  101.     long u2  ;        /* 4 -  ???? */
  102.     long date ;        /* 8 - Creation date of file */
  103.     short from ;        /*12 - index of first track */
  104.     short to ;         /*14 - index of last track */
  105.     ULONG  size_after ;    /*16 - total size of data after compression */
  106.     ULONG  size_before ;    /*20 - total size of data before compression */
  107.     long u3 ;        /*24 -  0 */
  108.     short cpu ;        /*28 -  Cpu type ( 1:68000, 2:68010, ... ) */
  109.     short copross ;     /*30 -  Cpu coprocessor ( 1:68881 ) */
  110.     short machine ;        /*32 -  Machine used ( 1:Amiga, 2:PC, ...) */
  111.     short u4 ;        /*34 -  ??? */
  112.     short cpu_speed ;    /*36 -  */
  113.     long time ;        /*38 -  Time to create archive in sec. */
  114.     short c_version ;    /*42 -  Version of creator (66, 67, 68) */
  115.     short n_version ;    /*44 -  Version needed to extract */
  116.     short disk_type ;    /*46 -  Disktype of archive */
  117.     short cmode ;        /*48 -  compression mode 0-4 */
  118. } ;
  119.  
  120. char THeader[18] ;
  121.  
  122. #define THEAD_IDENT(tab) (*((USHORT *) (tab+0 )))
  123. #define THEAD_TNUM(tab)  (*((SHORT *)  (tab+2 )))
  124. #define THEAD_CSIZE(tab) (*((ULONG *)  (tab+4 )))
  125. #define THEAD_SIZE(tab)  (*((USHORT *) (tab+10 )))
  126. #define THEAD_DCRC(tab)  (*((USHORT *) (tab+16)))
  127.  
  128. struct Track_Head        /*offset -  sizeof(Track_Head) = 18 */
  129. {
  130.     short delim ;        /* 0 - delimiter, 0x5452, is 'TR' */
  131.     short number ;        /* 2 - number of track, sometimes -1 */
  132.     ULONG size ;        /* 4 - size of data part */
  133.     USHORT plength ;    /* 8 - length of encoded data */
  134.     USHORT ulength ;    /*10 - length of non-encoded data */
  135.     short mode ;        /*12 - encryption mode(0: simple, 102: quick)*/
  136.     USHORT usum ;        /*14 - raw data checksum */
  137.     USHORT dcrc ;        /*16 - data CRC */
  138. } ;
  139.  
  140. static USHORT CRCTab[256]=
  141. {
  142.     0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
  143.     0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
  144.     0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
  145.     0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
  146.     0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
  147.     0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
  148.     0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
  149.     0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
  150.     0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
  151.     0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
  152.     0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
  153.     0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
  154.     0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
  155.     0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
  156.     0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
  157.     0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
  158.     0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
  159.     0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
  160.     0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
  161.     0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
  162.     0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
  163.     0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
  164.     0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
  165.     0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
  166.     0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
  167.     0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
  168.     0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
  169.     0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
  170.     0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
  171.     0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
  172.     0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
  173.     0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040
  174. };
  175.  
  176. USHORT DoBlockCRC(Mem, Size)
  177. UBYTE* Mem;
  178. int Size ;
  179. {
  180.     register USHORT CRC = 0;
  181.  
  182.     while(Size--)
  183.         CRC = CRCTab[((CRC ^ *Mem++) & 255)] ^ ((CRC >> 8) & 255);
  184.  
  185.     return(CRC) ;
  186. }
  187.  
  188. static void ReadError(s,n)
  189. char* s;
  190. int n;
  191. {
  192.     if ( MessageLevel >= VERBOSE )
  193.         printf("\tError reading %s (%d char read)\n",s,n) ;
  194. }
  195.  
  196. static void WriteError(s,n)
  197. char* s;
  198. int n;
  199. {
  200.     if ( MessageLevel >= VERBOSE )
  201.         printf("\tError writing %s (%d char written)\n",s,n) ;
  202. }
  203.  
  204. static void WhereInFile(fd,s)
  205. int fd ;
  206. char *s;
  207. {
  208.     off_t init;
  209.  
  210.     init = lseek(fd,(off_t) 0, L_INCR) ;
  211.     if ( MessageLevel >= DEBUG )
  212.         printf("\tStarting I/O of %s at offset %d\n",s,(int) init ) ;
  213. }
  214.  
  215. /*
  216.  * Reading a track in IoBuf.
  217.  *
  218.  */
  219.  
  220. static void ReadTrackHeader(fd)
  221. int fd ;
  222. {
  223.     int n_read ;
  224.  
  225.     WhereInFile(fd,"Track header") ;
  226.  
  227.     n_read = read(fd, THeader, sizeof(THeader) ) ;
  228.     if ( n_read != sizeof(THeader)  )    
  229.     {
  230.         ReadError("Theader DATA",n_read) ;
  231.         ErrorFlag = FATAL;
  232.         return;
  233.     }
  234.  
  235.     n_read = read(fd, (char *) &Crc, 2) ;
  236.     if ( n_read != 2 )    
  237.     {
  238.         ReadError("THeader CRC",n_read) ;
  239.         ErrorFlag = FATAL;
  240.     }
  241. }
  242.  
  243. static void VerifyTrackHeader()
  244. {
  245.     USHORT crc ;
  246.  
  247.     if ( THEAD_IDENT(THeader) != 0x5452 )    /* Magic string "TR" */
  248.     {
  249.         if ( MessageLevel >= VERBOSE )
  250.             printf("\tBAD THeader identifier: %x\n",
  251.                     (int) THEAD_IDENT(THeader) );
  252.  
  253.         ErrorFlag = FATAL ;
  254.         return ;
  255.     }
  256.  
  257.     crc = DoBlockCRC((UBYTE*) THeader, sizeof(THeader) ) ;
  258.  
  259.     if ( crc != Crc )
  260.     {
  261.         if ( MessageLevel >= VERBOSE )
  262.             printf("\tBAD THeader checksum. Read %d, computed %x\n",
  263.                                (int) Crc, (int) crc ) ;
  264.         ErrorFlag = FATAL ;    /* size is not sure */
  265.     }
  266.     else if ( MessageLevel >= DEBUG )
  267.         printf("\tTrack Header checksum OK (%x)\n",(int) crc ) ;
  268. }
  269.  
  270. static void ReadTrackData(fd)
  271. int fd ;
  272. {
  273.     int n_read ;
  274.  
  275.     if ( MessageLevel >= DEBUG )
  276.             printf("\tSize of track data: %d\n", (int) THEAD_CSIZE(THeader) );
  277.  
  278.     if ( MessageLevel >= VERBOSE )
  279.         {
  280.             printf("\tTrack: %2d ", (int) THEAD_TNUM(THeader)) ;
  281.     }
  282.  
  283.     n_read = read(fd, IoBuf, (int) THEAD_CSIZE(THeader)) ;
  284.     if ( n_read != THEAD_CSIZE(THeader) )    
  285.     {
  286.         ReadError("track data",n_read) ;
  287.         ErrorFlag = FATAL ; 
  288.         return;
  289.     }
  290. }
  291.  
  292. static void VerifyTrackData()
  293. {
  294.     USHORT crc ;
  295.  
  296.     crc = DoBlockCRC((UBYTE*) IoBuf, (int) THEAD_CSIZE(THeader) ) ;
  297.  
  298.     if ( crc != THEAD_DCRC(THeader) )
  299.     {
  300.         if ( MessageLevel >= VERBOSE )
  301.         printf("-BAD CRC: read %x, computed %x\n",
  302.                 (int) THEAD_DCRC(THeader), (int) crc ) ;
  303.         ErrorFlag = NONFATAL ;
  304.     }
  305.     else if ( MessageLevel >= VERBOSE )
  306.         printf("-GOOD CRC: %x\n",(int) crc ) ;
  307. }
  308.  
  309. static void ReadVerifyTrack(fd)
  310. int fd ;
  311. {
  312.     ReadTrackHeader(fd) ;
  313.  
  314.     if ( ErrorFlag == NOERROR )
  315.         VerifyTrackHeader() ;
  316.     
  317.     if ( ErrorFlag == NOERROR )
  318.         ReadTrackData(fd) ;
  319.  
  320.     if ( ErrorFlag == NOERROR )
  321.         VerifyTrackData() ;
  322.  
  323.     if ( ErrorFlag == NOERROR )
  324.         LastTrackRead = THEAD_TNUM(THeader) ;
  325. }
  326.  
  327. static void ReadTrack(fd)
  328. int fd ;
  329. {
  330.     ReadTrackHeader(fd) ;
  331.  
  332.     if ( ErrorFlag == NOERROR )
  333.         ReadTrackData(fd) ;
  334.  
  335.     if ( ErrorFlag == NOERROR )
  336.         LastTrackRead = THEAD_TNUM(THeader) ;
  337. }
  338.  
  339.  
  340. /*
  341.  * Writing a track
  342.  *
  343.  */
  344.  
  345. WriteTrackData(fd)
  346. int fd ;
  347. {
  348.     int n_write ;
  349.  
  350.     n_write = write(fd, IoBuf, (int) THEAD_CSIZE(THeader) ) ;
  351.     if ( n_write <  (int) THEAD_CSIZE(THeader) )    
  352.     {
  353.         WriteError("THeader DATA",n_write) ;
  354.         ErrorFlag = FATAL ; 
  355.         return ;
  356.     }
  357. }
  358.  
  359. WriteTrackHeader(fd)
  360. int fd ;
  361. {
  362.     int n_write ;
  363.  
  364.     n_write = write(fd, THeader, sizeof(THeader)) ;
  365.     if ( n_write < sizeof(THeader) )    
  366.     {
  367.         WriteError("THeader DATA",n_write) ;
  368.         ErrorFlag = FATAL ; 
  369.         return ;
  370.     }
  371.  
  372.     n_write = write(fd, (char *) &Crc, 2) ;
  373.     if ( n_write < 2 )    
  374.     {
  375.         WriteError("THeader CRC",n_write) ;
  376.         ErrorFlag = FATAL ;
  377.     }
  378. }
  379.  
  380. WriteTrack(fd)
  381. int fd ;
  382. {
  383.     WriteTrackHeader(fd) ;
  384.  
  385.     if ( ErrorFlag == NOERROR )
  386.         WriteTrackData(fd) ;
  387. }
  388.  
  389. /*
  390.  * Handling one file dms header
  391.  *
  392.  */
  393.  
  394. void VerifyDHeader()
  395. {
  396.     USHORT crc ;
  397.  
  398.     if ( strncmp(Ident, "DMS!", 4 ) )
  399.     {
  400.         if ( MessageLevel >= NORMAL )
  401.         printf("\tThis is *not* a dms archive\n") ;
  402.         ErrorFlag = FATAL ; 
  403.         return;
  404.     }
  405.  
  406.     crc = DoBlockCRC((UBYTE*) DHeaderIn, sizeof(DHeaderIn) ) ;
  407.  
  408.     if ( crc != Crc )
  409.     {
  410.         if ( MessageLevel >= VERBOSE )
  411.         printf("\tBAD file header checksum. Read %x, computed %x\n",
  412.                     (int) Crc, (int) crc) ;
  413.         ErrorFlag = FATAL ;
  414.     }
  415.     else if ( MessageLevel >= DEBUG )
  416.         printf("\tDms Header checksum OK (%x = %x)\n",
  417.                         (int) crc, (int) Crc );
  418. }
  419.  
  420. static void UpdateFileData()
  421. {
  422.     int medium ;
  423.  
  424.     if ( MessageLevel >= VERBOSE )
  425.     {
  426.         printf("\tContains tracks: %d to %d\n",
  427.         (int) DHEAD_FROM(DHeaderIn), (int) DHEAD_TO(DHeaderIn) );
  428.  
  429.        printf("\tCompression mode: %d\n", (int) DHEAD_MODE(DHeaderIn)) ;
  430.        printf("\tData sizes: raw: %d     compressed: %d\n",
  431.         (int) DHEAD_SIZE(DHeaderIn), (int) DHEAD_CSIZE(DHeaderIn));
  432.     }
  433.  
  434.     FirstTrack = (int) DHEAD_FROM(DHeaderIn) ;
  435.     LastTrack = (int) DHEAD_TO(DHeaderIn) ;
  436. }
  437.  
  438. void ReadDHeader(fd)
  439. int fd ;
  440. {
  441.     int n_read ;
  442.  
  443.     WhereInFile(fd,"Ident") ;
  444.  
  445.     n_read = read(fd, Ident, 4) ;
  446.     if ( n_read < 4 )    
  447.     {
  448.         ReadError("Ident",n_read) ;
  449.         ErrorFlag = FATAL ; 
  450.         return ;
  451.     }
  452.  
  453.     WhereInFile(fd,"DHeader") ;
  454.  
  455.     n_read = read(fd, DHeaderIn, sizeof(DHeaderIn)) ;
  456.     if ( n_read < sizeof(DHeaderIn) )    
  457.     {
  458.         ReadError("DHeader DATA",n_read) ;
  459.         ErrorFlag = FATAL ; 
  460.         return ;
  461.     }
  462.  
  463.     n_read = read(fd, (char *) &Crc, 2) ;
  464.     if ( n_read < 2 )    
  465.     {
  466.         ReadError("DHeader CRC",n_read) ;
  467.         ErrorFlag = FATAL ;
  468.     }
  469. }
  470.  
  471. void TreatDHeader(fd)
  472. int fd ;
  473. {
  474.     ReadDHeader(fd) ;
  475.  
  476.     if ( ErrorFlag == NOERROR )
  477.         VerifyDHeader() ;
  478.  
  479.     if ( ErrorFlag == NOERROR )
  480.         UpdateFileData() ;
  481. }
  482.  
  483. /*
  484.  * Writing the first part
  485.  *
  486.  */
  487.  
  488. static void WriteDHeader(fd)
  489. int fd ;
  490. {
  491.     int n_write;
  492.     USHORT crc ;
  493.  
  494.     crc = DoBlockCRC((UBYTE*) DHeaderOut, sizeof(DHeaderOut) ) ;
  495.  
  496.     n_write = write(fd, "DMS!", 4) ;
  497.     if ( n_write < 4 )    
  498.     {
  499.         WriteError("Ident",n_write) ;
  500.         ErrorFlag = FATAL ; 
  501.         return ;
  502.     }
  503.  
  504.     WhereInFile(FdOut,"DHeader") ;
  505.  
  506.     n_write = write(fd, DHeaderOut, sizeof(DHeaderOut)) ;
  507.     if ( n_write < sizeof(DHeaderOut) )    
  508.     {
  509.         WriteError("DHeader DATA",n_write) ;
  510.         ErrorFlag = FATAL ; 
  511.         return ;
  512.     }
  513.  
  514.     n_write = write(fd, (char *) &crc, 2) ;
  515.     if ( n_write < 2 )    
  516.     {
  517.         WriteError("DHeader CRC",n_write) ;
  518.         ErrorFlag = FATAL ;
  519.     }
  520. }
  521.     
  522. static void WriteFirstTracks()
  523. {
  524.     while ( LastTrackRead < (MediumTrack-1) )
  525.     {
  526.         ReadTrack(FdIn) ;
  527.  
  528.         if ( ErrorFlag == NOERROR )
  529.             WriteTrack(FdOut) ;
  530.  
  531.         if ( ErrorFlag != NOERROR )
  532.         break ;
  533.     }
  534. }
  535.  
  536. static void WriteLastTracks()
  537. {
  538.     while ( LastTrackRead < LastTrack )
  539.     {
  540.         ReadTrack(FdIn) ;
  541.  
  542.         if ( ErrorFlag == NOERROR )
  543.             WriteTrack(FdOut) ;
  544.  
  545.         if ( ErrorFlag != NOERROR )
  546.         break ;
  547.     }
  548. }
  549.  
  550. /*
  551.  * Writing Files
  552.  *
  553.  */
  554.  
  555. static int ComputeCompSize(first, last)
  556. int first,last ;
  557. {
  558.     int i, total ;
  559.  
  560.     if ( first == -1 )
  561.     {    total = CompText ; i=0 ; }
  562.     else
  563.     {    total = 0 ; i=first ; }
  564.  
  565.     for ( ; i <= last ; i++ )
  566.         total += CompSizes[i] ;
  567.  
  568.     return total ;
  569. }
  570.  
  571. static int ComputeSize(first, last)
  572. int first,last ;
  573. {
  574.     int i, total ;
  575.  
  576.  
  577.     if ( first == -1 )
  578.     {    total = RawText ; i=0 ; }
  579.     else
  580.     {    total = 0 ; i=first ; }
  581.  
  582.     for ( ; i <= last ; i++ )
  583.         total += RawSizes[i] ;
  584.  
  585.     return total ;
  586. }
  587.  
  588. static void WriteSecondFile()
  589. {
  590.     int i ;
  591.     
  592.     strcpy(IoBuf, "2_") ;
  593.     strcat(IoBuf,FileName) ;
  594.  
  595.     if ( MessageLevel >= VERBOSE )
  596.         printf("\tSecond output file name: %s\n",IoBuf) ;
  597.  
  598.     if ( (FdOut = open(IoBuf, O_WRONLY | O_CREAT, 0664)) == -1 )
  599.     {
  600.         fprintf(stderr,"\tError creating file: %s\n", IoBuf) ;
  601.         ErrorFlag = FATAL ;
  602.         return ;
  603.     }
  604.  
  605.     for ( i=0 ; i< sizeof(DHeaderIn); i++ )
  606.         DHeaderOut[i] = DHeaderIn[i] ;
  607.  
  608.     DHEAD_FROM(DHeaderOut) = MediumTrack ;
  609.     DHEAD_CSIZE(DHeaderOut) = 
  610.             (ULONG) ComputeCompSize(MediumTrack, LastTrack) ;
  611.     DHEAD_SIZE(DHeaderOut) = 
  612.             (ULONG) ComputeSize(MediumTrack, LastTrack) ;
  613.  
  614.     WriteDHeader(FdOut) ;
  615.  
  616.     if ( ErrorFlag == NOERROR )
  617.         WriteLastTracks() ;
  618.  
  619.     close(FdOut) ;
  620. }
  621.  
  622. static void WriteFirstFile()
  623. {
  624.     int i ;
  625.     
  626.     strcpy(IoBuf, "1_") ;
  627.     strcat(IoBuf,FileName) ;
  628.  
  629.     if ( MessageLevel >= VERBOSE )
  630.         printf("\tFirst output file name: %s\n",IoBuf) ;
  631.  
  632.     if ( (FdOut = open(IoBuf, O_WRONLY | O_CREAT, 0664)) == -1 )
  633.     {
  634.         fprintf(stderr,"\tError creating file: %s\n", IoBuf) ;
  635.         ErrorFlag = FATAL ;
  636.         return ;
  637.     }
  638.  
  639.     for ( i=0 ; i< sizeof(DHeaderIn); i++ )
  640.         DHeaderOut[i] = DHeaderIn[i] ;
  641.  
  642.     DHEAD_TO(DHeaderOut) = MediumTrack - 1 ;
  643.     DHEAD_CSIZE(DHeaderOut) = 
  644.             (ULONG) ComputeCompSize(-1, MediumTrack-1) ;
  645.     DHEAD_SIZE(DHeaderOut) = 
  646.             (ULONG) ComputeSize(-1, MediumTrack-1) ;
  647.  
  648.     WriteDHeader(FdOut) ;
  649.  
  650.     if ( ErrorFlag == NOERROR )
  651.         WriteFirstTracks() ;
  652.  
  653.     close(FdOut) ;
  654. }
  655.  
  656. /*
  657.  *
  658.  */
  659.  
  660. static void ComputeMediumTrack()
  661. {
  662.     int i, c, c1 ;
  663.  
  664.     if ( TrackNumber && !Percentage )    /* just a -t parameter */
  665.     {
  666.         if ( TrackNumber <= FirstTrack )
  667.         MediumTrack = FirstTrack + 1  ;
  668.         else if ( TrackNumber >= LastTrack )
  669.         MediumTrack = LastTrack - 1 ;
  670.         else
  671.         MediumTrack = TrackNumber ;
  672.  
  673.         printf("TrackNumber: %d   MediumTrack: %d\n",
  674.                          TrackNumber, MediumTrack) ;
  675.     }
  676.     else    /* a -p parameter (then -t ignored), or no parameter */
  677.     {
  678.         if ( !Percentage )
  679.         Percentage = RATIO ;    /* no parameter, split 70/30 */
  680.  
  681.         c1 = DHEAD_CSIZE(DHeaderIn) * Percentage / 100 ;
  682.         c = CompText ;
  683.         for ( i=0 ; (c<c1) && (i<MAXTRACKS) ; i++ )
  684.         c += CompSizes[i] ;
  685.         MediumTrack = i-1 ;
  686.         if ( MediumTrack <= FirstTrack )
  687.         MediumTrack = FirstTrack + 1  ;
  688.         if ( MediumTrack >= LastTrack )
  689.         MediumTrack = LastTrack - 1 ;
  690.         printf("\tPercentage: %d   MediumTrack: %d\n",
  691.                          Percentage, MediumTrack) ;
  692.     }
  693. }
  694.  
  695. static void SplitFile(file_)
  696. char * file_ ;
  697. {
  698.     if ( lseek(FdIn, (off_t) 0, L_SET) == -1 )
  699.     {                 /* return to beginning of file */
  700.         printf("Unable to lseek to beginning of file\n") ;
  701.         ErrorFlag = FATAL ;
  702.     }
  703.         
  704.     if ( ErrorFlag == NOERROR )
  705.     {
  706.         ReadDHeader(FdIn) ;        /* Skip header */
  707.         LastTrackRead = -1 ;
  708.     }
  709.  
  710.     if ( ErrorFlag == NOERROR )
  711.         WriteFirstFile() ;    
  712.  
  713.     if ( ErrorFlag == NOERROR )
  714.         WriteSecondFile() ;
  715.  
  716.     close(FdIn) ;
  717. }
  718.  
  719. static void ScanFile(file_)
  720. char * file_ ;
  721. {
  722.     if ( (FdIn = open(file_, 0)) == -1 )
  723.     {
  724.         fprintf(stderr,"\tError opening file: %s\n", file_) ;
  725.         return ;
  726.     }
  727.  
  728.     printf("Splitting file: %s\n", file_ ) ;
  729.  
  730.     TreatDHeader(FdIn) ;
  731.  
  732.     while ( LastTrackRead < LastTrack && ErrorFlag == NOERROR )
  733.     {
  734.         ReadVerifyTrack(FdIn) ;
  735.  
  736.         if ( LastTrackRead == -1 )
  737.         {
  738.         
  739.         CompText = (int) THEAD_CSIZE(THeader) ;
  740.         RawText = (int) THEAD_SIZE(THeader) ;
  741.         }
  742.         else
  743.         {
  744.             CompSizes[LastTrackRead] = (int) THEAD_CSIZE(THeader) ;
  745.             RawSizes[LastTrackRead] = (int) THEAD_SIZE(THeader) ;
  746.         }
  747.     }
  748.        
  749.     if ( ErrorFlag == NOERROR )
  750.         ComputeMediumTrack() ;
  751. }
  752.  
  753.  
  754. /*
  755.  * Various intialisations and command line handle
  756.  *
  757.  */
  758.  
  759. static PrintHelp()
  760. {
  761.     puts("Valid options are:") ;
  762.     puts("\t-p <n>: percentage") ;
  763.     puts("\t-t <n>: track number") ;
  764.     puts("\t-d : debug (very verbose)") ;
  765.     puts("\t-h,-? : help") ;
  766.  
  767.     exit(0) ;
  768. }
  769.  
  770. static int DecodeOption(argv, arg)
  771. char * argv[] ;
  772. int arg ;
  773. {
  774.         char *argp = argv[arg]+1 ;
  775.  
  776.         switch ( *argp )
  777.         {
  778.             case 't':
  779.              TrackNumber = atoi(argv[arg+1]) ;
  780.          if ( TrackNumber < 0 || TrackNumber > 79 )
  781.             TrackNumber = 0 ;
  782.                  return (arg+2) ;
  783.  
  784.             case 'p':
  785.              Percentage = atoi(argv[arg+1]) ;
  786.          if ( Percentage < 0 || Percentage > 100 )
  787.             Percentage = 0 ;
  788.                  return (arg+2) ;
  789.  
  790.             case 'd':
  791.          MessageLevel = DEBUG ;
  792.                  return (arg+1) ;
  793.  
  794.             case 'h':
  795.         case '?':
  796.         default:
  797.          PrintHelp() ;
  798.                  return (arg+1) ;        /* Not executed */
  799.  
  800.     }
  801. }
  802.  
  803.  
  804. void DecodeArgLine(argc, argv)
  805. int argc ;
  806. char * argv[] ;
  807. {
  808.       int arg ;
  809.  
  810.     if ( argc <= 1)
  811.     {
  812.         PrintHelp() ;
  813.     }
  814.  
  815.         for ( arg = 1; arg < argc ; )
  816.         {
  817.             if ( *argv[arg] != '-' )
  818.             {
  819.                 FileName = argv[arg] ;
  820.                 arg += 1 ;
  821.             }
  822.             else
  823.                 arg = DecodeOption(argv,arg) ;
  824.         }
  825. }
  826.  
  827. /*
  828.  * Main part
  829.  *
  830.  */
  831.  
  832. int main(argc,argv)
  833. int argc ;
  834. char ** argv ;
  835. {
  836.     DecodeArgLine(argc, argv) ;
  837.     
  838.     ScanFile(FileName) ;
  839.     
  840.     SplitFile(FileName) ;
  841.  
  842.     if (ErrorFlag )
  843.         return 1 ;
  844.     else
  845.         return 0 ;
  846. }
  847.